# coding: utf-8

from django.template import RequestContext
from django.shortcuts import render_to_response
from django.http import HttpResponse,HttpResponseRedirect
from django.core.paginator import Paginator, EmptyPage, InvalidPage
from django.http import request
from django.core.mail import send_mail

import MySQLdb
from swapper import load_model
import logging
import datetime
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex

from jd_oss.settings import *

class ServerError(Exception):
    """
    自定义异常
    """
    pass


def set_log(level, filename='jd_oss.log'):
    """
    return a log file object
    根据提示设置log打印
    """
    log_file = os.path.join(LOG_DIR, filename)
    # if not os.path.isfile(log_file):
    #     os.mknod(log_file)
    #     os.chmod(log_file, 0777)
    log_level_total = {'debug': logging.DEBUG,
                       'info': logging.INFO,
                       'warning': logging.WARN,
                       'error': logging.ERROR,
                       'critical': logging.CRITICAL
                       }
    logger_f = logging.getLogger('jd_oss')
    logger_f.setLevel(logging.DEBUG)
    # fh = logging.FileHandler(log_file)
    fh = logging.StreamHandler()
    fh.setLevel(log_level_total.get(level, logging.DEBUG))
    formatter = logging.Formatter(
        '%(asctime)s - %(filename)s:%(lineno)d - %(funcName)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    logger_f.addHandler(fh)
    return logger_f

logger = set_log(LOG_LEVEL)


def defend_attack(func):
    """
        6分钟内最大可尝试次数
    """
    def _deco(request, *args, **kwargs):
        if int(request.session.get('visit', 1)) > 10:
            logger.debug('请求次数: %s' % request.session.get('visit', 1))
            return HttpResponse('Forbidden', status=403)
        request.session['visit'] = request.session.get('visit', 1) + 1
        request.session.set_expiry(300)
        return func(request, *args, **kwargs)
    return _deco


def my_render(template, data, request):
    """
    自定义模板渲染
    """
    return render_to_response(
        template, data, context_instance=RequestContext(request)
    )

def send_mail_to(to_users,subject,message):
    """ 邮件发送
        send_mail(subject, message, from_email, recipient_list,
                  fail_silently=False, auth_user=None,
                  auth_password=None, connection=None, html_message=None)
    """
    to_users = to_users if hasattr(to_users, '__iter__') else [to_users]
    send_mail(subject=subject,
              message=message,
              from_email=EMAIL_HOST_USER,
              recipient_list=to_users)


def page_list_return(total, current=1):
    """
    page
    分页，返回本次分页的最小页数到最大页数列表
    """
    min_page = current - 2 if current - 4 > 0 else 1
    max_page = min_page + 4 if min_page + 4 < total else total

    return range(min_page, max_page + 1)


def pages(post_objects, request):
    """
    page public function , return page's object tuple
    分页公用函数，返回分页的对象元组
    """
    # 每页最大显示数量
    paginator = Paginator(post_objects, 20)
    try:
        current_page = int(request.GET.get('page', '1'))
    except ValueError:
        current_page = 1

    page_range = page_list_return(len(paginator.page_range), current_page)

    try:
        page_objects = paginator.page(current_page)
    except (EmptyPage, InvalidPage):
        page_objects = paginator.page(paginator.num_pages)

    if current_page >= 5:
        show_first = 1
    else:
        show_first = 0

    if current_page <= (len(paginator.page_range) - 3):
        show_end = 1
    else:
        show_end = 0

    # 所有对象， 分页器， 本页对象， 所有页码， 本页页码，是否显示第一页，是否显示最后一页
    return post_objects, paginator, page_objects,page_range, current_page, show_first, show_end


def get_modelfield(appname, modelname):
    """
    返回对应model的 表字段 和 verbose_name
    Args:
        appname(str) : django的appname
        modelname(str): model类命
    Returns:
        fielddic(dict):
            {
                'it_cost' : u'资产价格'
            }
    """
    modelobj = load_model(appname, modelname)
    fielddic = {}
    for field in modelobj._meta.fields:
        fielddic[field.name] = field.verbose_name
        # print '字段类型:',type(field).__name__
        # #返回的是‘charfield’,'textfield',等这些类型
    return fielddic


def get_choices(table_name, field):
    """
    返回指定字段的 distinct choices格式
    return:
        返回示例
        choice(tuple):
            (
                (1, u"使用中"),
                (2, u"未使用"),
                (3, u"未找到"),
                (4, u"已损坏"),
                (5, u"被借用"),
            )
    """
    db_name = DATABASES['default']['NAME']
    db_host = DATABASES['default']['HOST']
    db_port = int(DATABASES['default']['PORT'])
    db_user = DATABASES['default']['USER']
    db_password = DATABASES['default']['PASSWORD']
    sql = 'select distinct(%s) from %s; ' % (field, table_name)
    try:
        db = MySQLdb.connect(
            host=db_host,
            port=db_port,
            user=db_user,
            passwd=db_password,
            db=db_name, charset='utf8')
        cur = db.cursor(cursorclass=MySQLdb.cursors.DictCursor)
        cur.execute(sql)
        mysql_result = cur.fetchall()
    except Exception, e:
        print "Mysql connect error : ", e
        mysql_result = None
    finally:
        cur.close()
        db.close()

    if not mysql_result:
        print 'get mysql result field: \n ', e
        return None

    choices = [i for i in enumerate(map(lambda x:x[field], mysql_result))]
    return tuple(choices)


class PyCrypt(object):
    """
    密码类
    """

    def __init__(self, key):
        self.key = key
        self.mode = AES.MODE_CBC

    def encrypt(self, text):
        cryptor = AES.new(self.key, self.mode, b'0000000000000000')
        length = 16
        try:
            count = len(text)
        except TypeError:
            raise ServerError('Encrypt password error, TYpe error.')
        add = (length - (count % length))
        text += ('\0' * add)
        ciphertext = cryptor.encrypt(text)
        return b2a_hex(ciphertext)

    def decrypt(self, text):
        cryptor = AES.new(self.key, self.mode, b'0000000000000000')
        try:
            plain_text = cryptor.decrypt(a2b_hex(text))
        except TypeError:
            raise ServerError('Decrypt password error, TYpe error.')
        return plain_text.rstrip('\0')




CRYPTOR = PyCrypt(KEY)

#
# def require_role(role='user'):
#     """
#     decorator for require user role in ["super", "admin", "user"]
#     要求用户是某种角色 ["super", "admin", "user"]的装饰器
#     """
#
#     def _deco(func):
#         def __deco(request, *args, **kwargs):
#             request.session['pre_url'] = request.path
#             if not request.user.is_authenticated():
#                 return HttpResponseRedirect(reverse('login'))
#             if role == 'admin':
#                 # if request.session.get('role_id', 0) < 1:
#                 if request.user.role == 'CU':
#                     return HttpResponseRedirect(reverse('index'))
#             elif role == 'super':
#                 # if request.session.get('role_id', 0) < 2:
#                 if request.user.role in ['CU', 'GA']:
#                     return HttpResponseRedirect(reverse('index'))
#             return func(request, *args, **kwargs)
#
#         return __deco
#
#     return _deco
